/*  ----------------------------------------------------------------------------
 *  Arello Mobile
 *  Fast 3d Engine
 *  ----------------------------------------------------------------------------
 * Except where otherwise noted, this work is licensed under
 * http://creativecommons.org/licenses/by/3.0
 */

#include "TextureSpheric.h"
#include "Hardware.h"
#include <Gluck.h>

namespace liba
{
namespace lib3d
{
namespace hard
{
namespace directx8
{

D3DTRANSFORMSTATETYPE TextureSpheric::transform_mapper[8] =
{
	D3DTS_TEXTURE0, D3DTS_TEXTURE1,
	D3DTS_TEXTURE2, D3DTS_TEXTURE3,
	D3DTS_TEXTURE4, D3DTS_TEXTURE5,
	D3DTS_TEXTURE6, D3DTS_TEXTURE7
};

/*static D3DFORMAT PictureFormatRemapper[]
=
{
	D3DFMT_A8R8G8B8, //32
	D3DFMT_R8G8B8, D3DFMT_A8R8G8B8, // 24
	D3DFMT_R5G6B5, D3DFMT_A1R5G5B5, D3DFMT_A4R4G4B4, D3DFMT_A1R5G5B5 // 16
};*/

TextureSpheric::TextureSpheric(Hardware * hardware)
:	hard::TextureReflection( SPHERIC ),
	Dependent( hardware ),
	width( 0 ),
	height( 0 ),
	texture( 0 ),
	valid_flag( false )
{
	std::fill( spheric_matrix.m[0], spheric_matrix.m[4], float(0) );
	spheric_matrix.m[0][0] = 0.5f;
	spheric_matrix.m[1][1] = 0.5f;
	spheric_matrix.m[2][2] = 0.5f;
	spheric_matrix.m[3][3] = 1;
	spheric_matrix.m[0][3] = 0.5f;
	spheric_matrix.m[1][3] = 0.5f;
	spheric_matrix.m[2][3] = 0.5f;
}

TextureSpheric::~TextureSpheric()
{
	release();
}

void * TextureSpheric::lock(int plane, int * stride, int width, int height, const pictureformat::Format & pf)
{
	if( !valid_flag || width != this->width || height != this->height )
	{
		release();
		this->width = width;
		this->height = height;
		texture = create_internal_texture( width, height );
		if( !texture )
			throw Gluck(__FUNCTION__, "create_internal_texture() failed");
	}
	D3DLOCKED_RECT locked_rect;
	if( texture->LockRect( 0, &locked_rect, 0, D3DLOCK_NOSYSLOCK ) != D3D_OK )
		throw Gluck(__FUNCTION__, "texture->LockRect() failed");
	*stride = locked_rect.Pitch;
	return locked_rect.pBits;
}

void TextureSpheric::unlock(int plane)
{
	texture->UnlockRect( 0 );
//	texture->GenerateMipSubLevels();
	valid_flag = true;
}

bool TextureSpheric::is_valid()
{
	return valid_flag;
}

bool TextureSpheric::set_in_hardware(int stage, double factor, const Matrix & mat)
{
	if( hardware->test_and_set_last_texture(stage, this) )
		return true;
	hardware->get_device()->SetTexture( stage, texture );
	hardware->get_device()->SetTextureStageState( stage, D3DTSS_TEXCOORDINDEX , D3DTSS_TCI_CAMERASPACENORMAL | stage );
	hardware->get_device()->SetTextureStageState( stage, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2  );

	hardware->get_device()->SetTransform( transform_mapper[stage], &spheric_matrix );

	DWORD col = hardware->get_dword_color( Color(0,0,0), factor );
	hardware->get_device()->SetRenderState( D3DRS_TEXTUREFACTOR, col );

	hardware->get_device()->SetTextureStageState( stage, D3DTSS_COLORARG1, D3DTA_TEXTURE );
	hardware->get_device()->SetTextureStageState( stage, D3DTSS_COLORARG2, D3DTA_CURRENT );
	hardware->get_device()->SetTextureStageState( stage, D3DTSS_COLOROP,   D3DTOP_BLENDFACTORALPHA );
	hardware->get_device()->SetTextureStageState( stage, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
	hardware->get_device()->SetTextureStageState( stage, D3DTSS_ALPHAARG2, D3DTA_CURRENT );
	hardware->get_device()->SetTextureStageState( stage, D3DTSS_ALPHAOP,   D3DTOP_SELECTARG2 );
	return true;
}

void TextureSpheric::invalidate()
{
	valid_flag = false;
}

void TextureSpheric::release()
{
	valid_flag = false;

	if( texture )
		int ref_count = texture->Release();
	texture = 0;
}

IDirect3DTexture9 * TextureSpheric::create_internal_texture( int width, int height )
{
	IDirect3DTexture9 * texture = 0;
	hardware->get_device()->CreateTexture( width, height, 0, D3DUSAGE_AUTOGENMIPMAP, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture, 0 );
///	hardware->get_device()->CreateTexture( width, height, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture, 0 );
	return texture;
}

} // namespace directx8
} // namespace hard
} // namespace lib3d
} // namespace liba


